home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Code Resources / Jims CDEFs 1.50 / CDEF Source / source / cdefTog.c < prev    next >
Encoding:
Text File  |  1995-11-08  |  18.8 KB  |  670 lines  |  [TEXT/KAHL]

  1. //------------------------- © 1991-1995 by James G. Stout --------------------------
  2. // File        : cdefTog.c
  3. // Date        : November 2,1991
  4. // Author    : Jim Stout
  5. // Purpose    : A CDEF to implement Tog's buttons
  6. //            : use procID :   1104 * 16 + varCode 
  7. //            : when calling NewControl() or in your resource template.
  8. //            : This CDEF supports the System 7 style gray drawing of an
  9. //            : inactive control and the useWindFont varCode.
  10. //            :
  11. //            : If you find a use for this, I'd love to know about it.  Bug reports
  12. //            : are always interesting.
  13. //            :
  14. //            : Internet    : JimS@WRQ.COM(work hours, PST)
  15. //            : AppleLink   : WRQ            (daily)
  16. //            : CompuServe  : 73240,2052    (weekly or so)
  17. //            : AOL         : JasG        (weekly or so)
  18. //            : eWorld      : Jim Stout    (weekly or so)
  19. //----------------------------------------------------------------------------------
  20.  
  21. //#define _DEBUGCDEF 1        // allows inline debugging in a test project
  22. #define _USEOFFSCREEN 1
  23. #define _EMBOSS 1
  24.  
  25. #include "fatCDEF.h"
  26.  
  27. #include <Controls.h>
  28. #include <LowMem.h>
  29. #include <GestaltEqu.h>
  30. #include <Memory.h>
  31. #include <QDOffscreen.h>
  32. #include <ToolUtils.h>
  33. #include <Traps.h>
  34. #include <Types.h>
  35.  
  36. #include "colorCDEF.h"
  37. #include "grayCDEF.h"
  38. #include "miscCDEF.h"
  39.  
  40. #include "cdefTog.h"
  41.                                     
  42. #ifdef _DEBUGCDEF
  43. pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param);
  44. pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param)
  45. #else
  46.  
  47. //==================================================================================
  48. //    CDEF main
  49. //==================================================================================
  50.  
  51. pascal long main (short varCode, ControlHandle theCtl, short message, long param)
  52. #endif
  53. {
  54.     long        ret = 0L;
  55.     Point        p;
  56.     GrafPtr        thisPort;
  57.     CDEFHandle    hCdef;
  58.     SignedByte    cState, dState;
  59.     
  60. #include "fatEntry.c"
  61.     
  62.     cState = HGetState((Handle)theCtl);
  63.     HLock((Handle)theCtl);
  64.     if((**theCtl).contrlData) {
  65.         dState = HGetState((**theCtl).contrlData);
  66.         HLock((**theCtl).contrlData);
  67.     }
  68.  
  69. //----------------------------------------------------------------------------------
  70. // Process messages to control    
  71. //----------------------------------------------------------------------------------
  72.  
  73.     switch(message) {
  74.         
  75.         case initCntl:
  76.             GetPort(&thisPort);
  77.             hCdef = (CDEFHandle)NewHandle(sizeof(CDEFData));
  78.             if(hCdef) {
  79.                 (**hCdef).txFont = thisPort->txFont;
  80.                 (**hCdef).txSize = thisPort->txSize;
  81.                 (**theCtl).contrlData = (Handle)hCdef;
  82.                 dState = HGetState((**theCtl).contrlData);
  83.                 HLock((**theCtl).contrlData);
  84.             }
  85.         break;
  86.  
  87.         case dispCntl:
  88.             if((**theCtl).contrlData) {
  89.                 HUnlock((**theCtl).contrlData);
  90.                 DisposeHandle((**theCtl).contrlData);
  91.                 (**theCtl).contrlData = 0;
  92.             }
  93.         break;
  94.  
  95.         case drawCntl:
  96.             if((**theCtl).contrlVis != 0 &&
  97.                 ((WindowPeek)(**theCtl).contrlOwner)->visible)
  98.                 doDraw(theCtl, varCode);
  99.         break;
  100.  
  101.         case testCntl:
  102.             p.v=HiWord(param);
  103.             p.h=LoWord(param);
  104.             if(PtInRect(p,&(*theCtl)->contrlRect)) {
  105.                 ret = 1;
  106.             }
  107.         break;
  108.  
  109.         case  calcCRgns:
  110.             RectRgn((RgnHandle)(param & 0x7fffffffL), &(*theCtl)->contrlRect);
  111.         break;
  112.  
  113.         case calcCntlRgn:
  114.         case calcThumbRgn:
  115.             RectRgn((RgnHandle)(param), &(*theCtl)->contrlRect);
  116.         break;
  117.     }
  118.     
  119.     if((**theCtl).contrlData)
  120.         HSetState((**theCtl).contrlData, dState);
  121.     HSetState((Handle)theCtl, cState);
  122.  
  123. #include "fatExit.c"
  124.     
  125.     return (ret);
  126. }
  127.  
  128. //==================================================================================
  129. // If running with System 7, use DeviceLoop to gracefully handle multiple screens.
  130. // Simulate DeviceLoop if using System 6...
  131. //==================================================================================
  132.  
  133. static void doDraw(ControlHandle theCtl, short varCode)
  134. {
  135.     short                    saveMode, txF, txS;
  136.     unsigned char            saveFace;
  137.     GrafPtr                    savePort, thisPort;
  138.     devLoopHandle            hDl;
  139.     RgnHandle                saveClip, hRgn;
  140.     DeviceLoopDrawingUPP    drawControlUPP;
  141.  
  142. //----------------------------------------------------------------------------------
  143. // set window font & size info    
  144. //----------------------------------------------------------------------------------
  145.     GetPort(&savePort);
  146.     SetPort((**theCtl).contrlOwner);
  147.     GetPort(&thisPort);
  148.     
  149.     saveMode = thisPort->txMode;
  150.     saveFace = thisPort->txFace;
  151.     
  152.     if(!(varCode & useWindFont)) {                // use system font
  153.         txF = thisPort->txFont;                    // save current
  154.         txS = thisPort->txSize;
  155.         TextFont(LMGetSysFontFam());            // set system as current
  156.         TextSize(LMGetSysFontSize());
  157.         TextFace(normal);
  158.     }
  159.     TextMode(srcOr);
  160.  
  161. //----------------------------------------------------------------------------------
  162. //    Create our data handle to pass to DeviceLoop
  163. //----------------------------------------------------------------------------------
  164.  
  165.     hDl = (devLoopHandle)NewHandle(sizeof(devLoopData));
  166.     if(hDl) {
  167.         drawControlUPP = NewDeviceLoopDrawingProc(drawControl);
  168.         
  169.         (**hDl).theCtl = theCtl;
  170.         (**hDl).varCode = varCode;
  171.         (**hDl).controlRect = (**theCtl).contrlRect;
  172.  
  173. //----------------------------------------------------------------------------------
  174. //    Do the clip region properly.  Thanks Ari!
  175. //----------------------------------------------------------------------------------
  176.  
  177.         saveClip = NewRgn();
  178.         GetClip(saveClip);
  179.         
  180.         hRgn = NewRgn();
  181.         RectRgn(hRgn, &(**hDl).controlRect);
  182.         SectRgn(saveClip, hRgn, hRgn);
  183.         
  184.         if(EmptyRgn(hRgn)) {                                    // if empty, don't waste
  185.             DisposeRgn(saveClip);                                // time drawing...
  186.             DisposeRgn(hRgn);
  187.             return;
  188.         }        
  189.  
  190. //----------------------------------------------------------------------------------
  191. //    Call DeviceLoop to take care of our drawing
  192. //----------------------------------------------------------------------------------
  193.         
  194.         if(getOSVers() >= 0x0700) {
  195.             DeviceLoop (hRgn, drawControlUPP, (long)hDl, 0);
  196.         }
  197.         else {
  198.             sys6DeviceLoop (hRgn, drawControlUPP, (long)hDl, 0);
  199.         }
  200.         
  201.         SetClip(saveClip);        
  202.         DisposeRgn(hRgn);
  203.         DisposeHandle((Handle)hDl);
  204.         DisposeRoutineDescriptor(drawControlUPP);
  205.     }
  206.  
  207. //----------------------------------------------------------------------------------
  208. // restore window font & size info    
  209. //----------------------------------------------------------------------------------
  210.  
  211.     if(!(varCode & useWindFont)) {
  212.         TextFont(txF);
  213.         TextSize(txS);
  214.     }
  215.     TextMode(saveMode);
  216.     TextFace(saveFace);
  217.     SetPort(savePort);
  218. }
  219.  
  220. //==================================================================================
  221. // main drawing routine for all variations of the control.  Also
  222. // handles setting of colors, inactive control drawing.
  223. //
  224. // This is called by DeviceLoop, but in this case, we just pay attention to the
  225. // "depth" and "userData" parameters.
  226. //==================================================================================
  227.  
  228. pascal void drawControl (short depth, short dFlags, GDHandle theDevice, long userData)
  229. {
  230.  
  231. #pragma unused(dFlags, theDevice)
  232.  
  233.     ControlHandle    theCtl;
  234.     short            varCode, qdVers, lnHt, lnAdj;
  235.     OSErr            err;
  236.     Rect            ctlRect, offRect;
  237.     FontInfo        f;
  238.     PenState        savePen;
  239.     Boolean            grayOK = false, inColor = false, inactive = false, bwPort = true;
  240.     Boolean            bgInColor = false, useOffscreen = false;
  241.     RGBColor        saveFore={0,0,0}, saveBack={-1,-1,-1}, rgbGray;
  242.     GrafPtr            thisPort;
  243.     CGrafPtr        savePort, offPort=0;
  244.     GDHandle        saveDevice;
  245.     PixMapHandle    offPix;
  246.     CDEFHandle        hCdef;
  247.     devLoopHandle    hDl;
  248.     
  249. //----------------------------------------------------------------------------------
  250. // Can we draw?
  251. //----------------------------------------------------------------------------------
  252.  
  253.     hDl = (devLoopHandle)userData;                        // need control & varCode
  254.     if(hDl) {
  255.         theCtl = (**hDl).theCtl;
  256.         varCode = (**hDl).varCode;
  257.     }
  258.     else
  259.         return;
  260.         
  261.     hCdef = (CDEFHandle)(**theCtl).contrlData;
  262.     if(!hCdef)
  263.         return;
  264.         
  265. //----------------------------------------------------------------------------------
  266. // Initialize for drawing    
  267. //----------------------------------------------------------------------------------
  268.  
  269.     if(varCode & useWindFont)
  270.         varCode ^= useWindFont;
  271.     
  272.     if((*theCtl)->contrlHilite == 255)
  273.         inactive = true;
  274.         
  275.     GetPort(&thisPort);
  276.     ctlRect = offRect = (*theCtl)->contrlRect;
  277.     
  278.     if((thisPort->txFont != (**hCdef).txFont) ||        // if font changed,
  279.         (thisPort->txSize != (**hCdef).txSize)) {        // clear rect to erase
  280.         (**hCdef).txFont = thisPort->txFont;            // old font
  281.         (**hCdef).txSize = thisPort->txSize;
  282.         (**hCdef).txFace = thisPort->txFace;
  283.         EraseRect(&ctlRect);
  284.     }
  285.     
  286.     GetPenState(&savePen);
  287.  
  288. //----------------------------------------------------------------------------------
  289. //    Should we draw in color?
  290. //
  291. //    What kind of port are we drawing to ?  DeviceLoop may have called us with a 
  292. //    depth > 1, but for an old-style 1 bit port ( but the GDevice is multi-bit). 
  293. //
  294. //    If so, then set depth to 1 unless we have Color Quickdraw and want to use
  295. //    offscreen drawing to force color controls in the old style grafport.
  296. //----------------------------------------------------------------------------------
  297.  
  298.     if((((CGrafPtr)thisPort)->portVersion & 0x8000))    // have a color grafPort
  299.         bwPort = false;
  300.  
  301. #ifdef _USEOFFSCREEN
  302.         
  303.     qdVers = getQDVers();
  304.     
  305.     if(bwPort && qdVers < gestalt32BitQD12)                // can't force colors
  306.         depth = 1;                                        // in b&w port unless
  307.                                                         // we have ColorQD
  308. #else
  309.  
  310.     if(bwPort)
  311.         depth = 1;
  312.  
  313. #endif
  314.  
  315.     if(depth > 2) {                                        // either color port or
  316.         inColor = true;                                    // color GDevice
  317.         saveColors(&saveFore, &saveBack);
  318.         bgInColor = true;
  319.         if(saveBack.red == 65535 &&                        // is bg white?
  320.             saveBack.green == 65535 &&
  321.             saveBack.blue == 65535)
  322.             bgInColor = false;
  323.     }
  324.  
  325. //----------------------------------------------------------------------------------
  326. //    Figure out how we should draw - offscreen or not...
  327. //----------------------------------------------------------------------------------
  328.  
  329. #ifdef _USEOFFSCREEN
  330.  
  331.     if(inColor && qdVers >= gestalt32BitQD12) {            // can use GWorlds
  332.         if(bwPort)                                        // to get 3D in b&w ports
  333.             useOffscreen = true;
  334.         else
  335.         if(bgInColor)                                    // or to avoid flicker on
  336.             useOffscreen = true;                        // control titles
  337.     }
  338.     
  339. //----------------------------------------------------------------------------------
  340. // Can we draw off screen ?
  341. //----------------------------------------------------------------------------------
  342.  
  343.     if(useOffscreen) {
  344.         err = NewGWorld(&offPort, 0, &offRect, nil, nil, 0L);
  345.         if(err == noErr && offPort) {                    // got offscreen port
  346.             offPix = getLockedPixels(&offPort, qdVers);    // get pixels
  347.             if(offPix) {
  348.                 GetGWorld(&savePort, &saveDevice);        // save old port stuff
  349.                 SetGWorld(offPort, nil);                // set to offscreen port
  350.                 SetOrigin(offRect.left, offRect.top);    // and initialize it...
  351.                 RGBForeColor(&saveFore);            
  352.                 RGBBackColor(&saveBack);
  353.                 TextFont(thisPort->txFont);
  354.                 TextSize(thisPort->txSize);
  355.                 TextFace(thisPort->txFace);
  356.                 TextMode(srcOr);
  357.                 EraseRect(&offRect);
  358.             }
  359.             else {
  360.                 DisposeGWorld(offPort);
  361.                 offPort = 0;
  362.             }
  363.         }
  364.         else
  365.             offPort = 0;
  366.     }
  367.  
  368. #endif    // _USEOFFSCREEN
  369.     
  370. //----------------------------------------------------------------------------------
  371. //    Set a 1 by 1, solid pattern pen for our drawing.
  372. //----------------------------------------------------------------------------------
  373.  
  374.     PenSize(1,1);
  375.     PenPat( (ConstPatternParam) "\xff\xff\xff\xff\xff\xff\xff\xff");
  376.  
  377. //----------------------------------------------------------------------------------
  378. //    Get font info so the title lines up correctly
  379. //----------------------------------------------------------------------------------
  380.  
  381.     GetFontInfo(&f);                                    // needed for title routine
  382.     lnAdj = f.descent + f.leading;                
  383.     lnHt = f.ascent + lnAdj;
  384.         
  385. //----------------------------------------------------------------------------------
  386. // Draw the control title, in cTextColor or gray if it is inactive    
  387. //----------------------------------------------------------------------------------
  388.  
  389.     if(inColor) {
  390.  
  391. #ifdef _EMBOSS    
  392.         if(bgInColor) {
  393.             ForeColor(whiteColor);
  394.             drawTitle (theCtl, &offRect, lnHt, lnAdj, EMBOSS, !PUSHED);
  395.         }
  396. #endif
  397.  
  398.         setPartColor(theCtl, cTextColor, true);
  399.         grayOK = getGray(&rgbGray);
  400.         if(grayOK && inactive)
  401.             RGBForeColor(&rgbGray);
  402.     }
  403.     
  404.     drawTitle(theCtl, &offRect, lnHt, lnAdj, NORMAL, !PUSHED);
  405.  
  406. //----------------------------------------------------------------------------------
  407. //    If we drew offscreen, restore the onscreen port and blit the control title.
  408. //----------------------------------------------------------------------------------
  409.  
  410. #ifdef _USEOFFSCREEN
  411.  
  412.     if(offPort) {
  413.         SetGWorld(savePort, saveDevice);
  414.         
  415. //----------------------------------------------------------------------------------
  416. //    Use CopyBits to get the titles onscreen (avoiding flicker on embossed titles).
  417. //----------------------------------------------------------------------------------
  418.  
  419.         restoreColors(&saveFore, &saveBack);
  420.  
  421.         if((**theCtl).contrlTitle[0])
  422.             CopyBits( &WINBITMAP( offPort ), &WINBITMAP( savePort ),
  423.                           &offRect, &ctlRect, transparent, nil );
  424.                           
  425.         unlockPixels(offPix, qdVers);
  426.         DisposeGWorld(offPort);
  427.     }
  428.  
  429. #endif // _USEOFFSCREEN
  430.  
  431. //----------------------------------------------------------------------------------
  432. //    Draw control indicator directly to the screen
  433. //----------------------------------------------------------------------------------
  434.  
  435.     if(inColor) {
  436.         RGBBackColor(&saveBack);                        // background
  437.         setPartColor(theCtl, cFrameColor, true);        // foreground
  438.         grayOK = getGray(&rgbGray);
  439.         if(grayOK && inactive)
  440.             RGBForeColor(&rgbGray);
  441.     }
  442.     
  443.     drawTog(theCtl, &ctlRect, inColor);
  444.     
  445. //----------------------------------------------------------------------------------
  446. // gray inactive controls the System 6 way if needed (couldn't get gray for title)
  447. //----------------------------------------------------------------------------------
  448.         
  449.     if(!grayOK && inactive) {                        // gray out the old way    
  450.         PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
  451.         PenMode(patBic);
  452.         ctlRect.left+=18;                            // not the indicator area
  453.         ClipRect(&ctlRect);
  454.         PaintRect(&ctlRect);
  455.     }
  456.  
  457. //----------------------------------------------------------------------------------
  458. // Clean up and leave    
  459. //----------------------------------------------------------------------------------
  460.                   
  461.     if(inColor)
  462.         restoreColors(&saveFore, &saveBack);
  463.     SetPenState(&savePen);
  464. }
  465.  
  466. //==================================================================================
  467. //    The "Tog Button" drawing routine
  468. //==================================================================================
  469.  
  470. static void drawTog(ControlHandle theCtl, Rect *offRect, Boolean inColor)
  471. {
  472.     Rect        r;
  473.     Point        p;
  474.     short        i,x,y;
  475.     RGBColor    saveFore,rgbA = {0xAAAA,0xAAAA,0xAAAA};
  476.     GrafPtr        thisPort;
  477.     
  478.     GetPort(&thisPort);
  479.     
  480. // Draw the diamond shaped control 
  481.  
  482.     if(inColor)
  483.         GetForeColor(&saveFore);
  484.         
  485.     r = *offRect;
  486.     p.h = r.left+2;                                    // get pen loc for drawing
  487.     p.v = r.bottom - (r.bottom - r.top)/2 - 1;
  488.     
  489.     MoveTo(p.h,p.v);                                // button frame            
  490.     LineTo(p.h+7,p.v+7);
  491.     LineTo(p.h+14,p.v);
  492.     LineTo(p.h+7,p.v-7);
  493.     LineTo(p.h,p.v);
  494.  
  495.     ForeColor(whiteColor);                            // erase center
  496.     if(!inColor)
  497.         BackColor(whiteColor);                        // just to be sure…
  498.     MoveTo(p.h+1,p.v);
  499.     Line(6,-6);
  500.     for(i=0;i<6;i++) {
  501.         Move(0,1);
  502.         Line(-5,5);
  503.         Move(0,1);
  504.         Line(6,-6);
  505.     }
  506.     if(!inColor)
  507.         ForeColor(blackColor);
  508.             
  509.     if(inColor) {
  510.         RGBForeColor(&rgbA);                        // add 3D shading
  511.         MoveTo(p.h,p.v-1);
  512.         LineTo(p.h+7, p.v-8);
  513.         LineTo(p.h+14, p.v-1);
  514.         ForeColor(whiteColor);
  515.         Move(0,2);
  516.         LineTo(p.h+8, p.v+7);
  517.         Move(-2,0);
  518.         LineTo(p.h,p.v+1);
  519.         
  520.         RGBForeColor(&saveFore);
  521.     }
  522.     
  523.     if((*theCtl)->contrlHilite == 1) {                // hilited button
  524.         MoveTo(p.h+1,p.v);
  525.         LineTo(p.h+7,p.v+6);
  526.         LineTo(p.h+13,p.v);
  527.         LineTo(p.h+7,p.v-6);
  528.         LineTo(p.h+1,p.v);
  529.     }
  530.     
  531.     if((*theCtl)->contrlValue != OFF) {                // button center            
  532.         x = p.h+4;
  533.         y = p.v;
  534.         for(i=1;i<=4;i++) {
  535.             MoveTo(x,y);
  536.             LineTo(x+3,y+3);
  537.             x++;
  538.             y--;
  539.         }
  540.         x = p.h+5;
  541.         y = p.v;
  542.         for(i=1;i<=3;i++) {
  543.             MoveTo(x,y);
  544.             LineTo(x+2,y+2);
  545.             x++;
  546.             y--;
  547.         }
  548.     }
  549. }
  550. //==================================================================================
  551. // Draw the control titles - handles multiple lines and 3D embossing
  552. //==================================================================================
  553.  
  554. static void drawTitle (ControlHandle theCtl, Rect *offRect, short lnHt, 
  555.                         short lnAdj, Boolean emboss, Boolean pushed)
  556. {
  557.     Rect    r;
  558.     short     inx=1,lnCnt=1,lnSpace,ctlSpace,v,h,adj=0;
  559.     Str255    s;
  560.     
  561.     r = *offRect;
  562.         
  563.     do {                                                // count number of lines
  564.         if((*theCtl)->contrlTitle[inx++] == 0x0d)    
  565.             lnCnt++;
  566.     }while (inx <= (*theCtl)->contrlTitle[0]);
  567.     
  568.     lnSpace = lnCnt * lnHt;                                // required space
  569.     ctlSpace = r.bottom - r.top;                        // available height
  570.     v = r.bottom;                                        // baseline
  571.     v-=(ctlSpace - lnSpace)/2;                            // minus free space
  572.     v-=lnAdj;                                            // minus descent+leading
  573.     v-=((lnCnt-1)*lnHt);                                // minus other lines
  574.                                                         // v is now base for line 1
  575.     for(inx=1;inx<=lnCnt;inx++) {
  576.         getNextLine((*theCtl)->contrlTitle, s, inx);
  577.         if(s[0]) {
  578.             h = r.left + 20;
  579.             if(emboss & pushed)
  580.                 adj = -1;
  581.             else
  582.             if(emboss) 
  583.                 adj = 1;
  584.     
  585.             MoveTo(h+adj, v+adj);
  586.             DrawString(s);
  587.         }
  588.         v+=lnHt;
  589.     }
  590. }
  591. //==================================================================================
  592. // Grab the next line of a control title (assumes lines separated by CR)
  593. //==================================================================================
  594.  
  595. static void getNextLine(Str255 t, Str255 s, short line)
  596. {
  597.     short    inx=1,len=0,lnCnt=1;
  598.     
  599.     s[0] = 0;                        // always default to null string
  600.     
  601.     do {
  602.         if(t[inx] == 0x0d)            // next line
  603.             lnCnt++;
  604.         else
  605.         if(lnCnt == line) {            // return this line
  606.             len++;
  607.             s[0] = len;
  608.             s[len] = t[inx];
  609.         }
  610.         inx++;
  611.     }while (inx <= t[0]);
  612. }
  613.  
  614.  
  615. #ifdef _USEOFFSCREEN
  616.  
  617. //==================================================================================
  618. // Lock down the offPort pixels and return a locked handle to the locked pixels
  619. //==================================================================================
  620.  
  621. static PixMapHandle getLockedPixels(CGrafPtr * offPort, short qdVers)
  622. {
  623.     PixMapHandle    pmHdl;
  624.     
  625.     if(qdVers >= gestalt32BitQD13) {                    // no bug in the
  626.         pmHdl = GetGWorldPixMap(*offPort);                // GetGWorldPixMap routine
  627.         if(!LockPixels(pmHdl)) {
  628.                 pmHdl = 0;
  629.         }
  630.     }
  631.     else
  632.         pmHdl = (*offPort)->portPixMap;
  633.     
  634.     if(pmHdl)
  635.         HLock((Handle)pmHdl);
  636.     return(pmHdl);
  637. }
  638.  
  639. //==================================================================================
  640. //    Unlock PixMapHandle & pixels
  641. //==================================================================================
  642.  
  643. static void unlockPixels(PixMapHandle pmHdl, short qdVers)
  644. {    
  645.     if(pmHdl) {
  646.         HUnlock((Handle)pmHdl);
  647.         if(qdVers >= gestalt32BitQD13) {                // no bug in the
  648.             UnlockPixels(pmHdl);                        // GetGWorldPixMap routine
  649.         }
  650.     }
  651. }
  652.  
  653. //==================================================================================
  654. //    Return QD version number from Gestalt 
  655. //==================================================================================
  656.  
  657. static short getQDVers()        
  658. {
  659.     OSErr        err;
  660.     long        gResult;
  661.     
  662.     if(trapAvailable(_Gestalt)) {        
  663.         err = Gestalt(gestaltQuickdrawVersion,&gResult);
  664.         if(err == noErr)
  665.             return(LoWord(gResult));
  666.     }
  667.     return(gestaltOriginalQD);
  668. }
  669.  
  670. #endif // _USEOFFSCREEN